/*
 * Copyright (C), 2013-2017, 工人网
 * FileName: SecretKeyFilter.java
 * Author:   yjg
 * Date:     2017年8月2日 上午10:18:08
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.gongren.oddjob.filter;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gongren.oddjob.commons.constant.RequestConstant;
import com.gongren.oddjob.utils.ParamSignUtils;
import com.gongren.oddjob.utils.StringUtils;

/**
 * 功能描述:
 * 
 * Author: yjg@gongren.com Date: 2017年8月2日 上午10:18:08
 */
public class SecretKeyFilter extends BaseFilter {

	private String secretKey = "Abc23456";
	public final static long milliseconds = 1000;
	public final static long minute = milliseconds * 60;
	public final static long hours = minute * 60;
	public final static long day = hours * 60;
	public final static Pattern pattern = Pattern.compile("[0-9]*");

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest servletRequest = (HttpServletRequest) request;
		HttpServletResponse servletResponse = (HttpServletResponse) response;
		String requestURI = servletRequest.getRequestURI();
		logger.info("请求地址为:{}", requestURI);

		if (requestURI.indexOf("login") > -1 || requestURI.indexOf("error") > -1) {
			chain.doFilter(servletRequest, servletResponse);
			return;
		}

		String token = servletRequest.getParameter(RequestConstant.param.token);
		logger.info("token={}", token);
		String dispatcherUrl = "/error";
		if (token != null && token.split("/").length > 1) {
			String[] tokenSplit = token.split("/");
			if (pattern.matcher(tokenSplit[1].toString().trim()).matches()) {
				// token令牌 30天的有效期
				if (compareDateToDay(new Long(tokenSplit[1].toString()), 30) >= 0) {
					if (verifyKey(servletRequest)) {
						request.setAttribute("principal", request.getParameter("principal"));
						request.setAttribute("type", request.getParameter("type"));
						chain.doFilter(request, response);
					} 
				} else {
		            dispatcherUrl = "/login";
				}
			}
		} 
		RequestDispatcher rd=request.getRequestDispatcher(dispatcherUrl);
        rd.forward(request,response);
	}

	/**
	 * 功能描述:
	 * 
	 * @param timestamp
	 * @param dayday
	 * @return Author: yjg@gongren.com Date: 2017年8月22日 下午7:44:02 Version: 1.0.0
	 */
	private int compareDateToDay(Long timestamp, int amount) {
		long deadlineTimeMillis = timestamp + amount * day;
		long currentTimeMillis = System.currentTimeMillis();
		return deadlineTimeMillis > currentTimeMillis ? 1 : (deadlineTimeMillis == currentTimeMillis ? 0 : -1);
	}

	/**
	 * 功能描述:
	 * 
	 * @param servletRequest
	 * @return true/false 校验结果 Author: yjg@gongren.com Date: 2017年8月2日 上午11:03:41
	 *         Version: 1.0.0
	 */
	private boolean verifyKey(HttpServletRequest servletRequest) {
		if (servletRequest.getParameterNames() == null)
			return false;
		Enumeration<?> em = servletRequest.getParameterNames();
		Map<String, String> paramValues = new HashMap<String, String>();
		String uptime = null, requestorSign = null, token = null;
		while (em.hasMoreElements()) {
			String name = (String) em.nextElement();
			String value = servletRequest.getParameter(name);

			if (name.toLowerCase().equals(RequestConstant.param.uptime)) {
				uptime = value;
			} else if (name.toLowerCase().equals(RequestConstant.param.sign)) {
				requestorSign = value;
				logger.info("请求签名为:{}", requestorSign);
				continue;
			} else if (name.toLowerCase().equals(RequestConstant.param.token)) {
				token = value;
				logger.info("请求token为:{}", token);
				continue;
			}
			paramValues.put(name, value);
		}

		if (StringUtils.isNotEmpty(uptime) && StringUtils.isNotEmpty(requestorSign)
				&& pattern.matcher(uptime.trim()).matches()) {
			long clientTime = Long.parseLong(uptime.trim());
			long serviceTime = System.currentTimeMillis();
			if ((serviceTime - clientTime) > minute || (serviceTime - clientTime) < 0) {
				logger.info("请求超时,clientTime={},serviceTime={}", clientTime, serviceTime);
				return false;
			}
		} else {
			logger.info("请求参数不合法:timestamp={},requestorSign={}", uptime, requestorSign);
			return false;
		}

		HashMap<String, String> signMap = ParamSignUtils.sign(paramValues, null, secretKey);
		if (signMap != null) {
			String certifiedSign = signMap.get(ParamSignUtils.SIGN);
			logger.info("认证签名为:{}", certifiedSign);
			// 存在并发问题
			if (StringUtils.isNotEmpty(certifiedSign) && requestorSign.equals(certifiedSign)) {
				logger.info("请求成功");
				return true;
			}
		}
		return false;
	}
}
